﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.IO.Compression;
using Amazon;
using Amazon.S3;
using Amazon.S3.Model;
using Amazon.S3.Transfer;
using DevToolBox.Common;
using DevToolBox.Cloud.Common;

namespace DevToolBox.Cloud.Amazon
{
    public class AmazonS3Transactions : IDownloadable
    {
        private string tenantBucketNamePrefix = "BUCKET_FOR_TENANTID_";
        private AmazonS3Config s3config = null;
        private TransferUtilityConfig transferConfig = null;
        private TransferUtility client;
        private AmazonS3 s3client;

        public AmazonS3Transactions()
        {
            s3config = new AmazonS3Config();
            s3config.UseSecureStringForAwsSecretKey = false;
            transferConfig = new TransferUtilityConfig();
            transferConfig.DefaultTimeout = SearchConstants.NOT_FOUND;
            s3client = AWSClientFactory.CreateAmazonS3Client(s3config);
            client = new TransferUtility(s3client, transferConfig);
        }

        public void UploadFile(object contextData, object value)
        {
            if (contextData != null && value != null)
            {
                string tenantId = Convert.ToString(contextData);
                string basePath = ConfigParamReader.GetString("PathToLogMessages");
                DateTime date = Convert.ToDateTime(value);
                string logPath = basePath + date.ToString(DateTimeFormat.SHORT_DATE_FORMAT) +
                                 "_Tenant_" + tenantId + "_log.txt";

                if (File.Exists(logPath))
                {
                    FileInfo fi = new FileInfo(logPath);
                    string compressedFileName = FileUtil.Compress(fi);

                    if (compressedFileName != null)
                    {
                        compressedFileName = basePath + compressedFileName + ".gz";
                        string tenantBucketName = tenantBucketNamePrefix + tenantId;
                        client.Upload(compressedFileName, tenantBucketName, GetLogFileKey(tenantId, date));
                        File.Delete(compressedFileName); //The compressed file is deleted
                    }
                }
            }
        }

        private string GetLogFileKey(string tenantId, DateTime date)
        {
            string fileKey = "LOG_FOR_TENANT_ID_" + tenantId + "_" + date.ToString(DateTimeFormat.SHORT_DATE_FORMAT);
            return fileKey;
        }

        public string DownloadFile(object contextData, object value)
        {
            string tenantId = Convert.ToString(contextData);
            DateTime date = Convert.ToDateTime(value);
            string logPath = GetCompressedLogPath(tenantId, date);
            string tenantBucketName = tenantBucketNamePrefix + tenantId;
            try
            {
                client.Download(logPath, tenantBucketName, GetLogFileKey(tenantId, date));
            }
            catch { }//If the download fails means that the given key is not available

            if (File.Exists(logPath))
            {
                FileInfo fi = new FileInfo(logPath);
                FileUtil.Decompress(fi);
                return logPath;
            }
            else
            {
                return null;
            }
        }

        private string GetCompressedLogPath(string tenantId, DateTime date)
        {
            string basePath = ConfigParamReader.GetString("PathToLogMessages");
            string logPath = basePath + date.ToString(DateTimeFormat.SHORT_DATE_FORMAT) +
                             "_Tenant_" + tenantId + "_TMP_log.txt.gz";
            return logPath;
        }

        private string GetDecompressedLogPath(string tenantId, DateTime date)
        {
            return GetCompressedLogPath(tenantId, date).ToUpper().Replace(".GZ", string.Empty);
        }

        public List<string> Read(object contextData, object value)
        {
            if (contextData != null && value != null)
            {
                var inputParams = (object[])contextData;
                string tenantId = Convert.ToString(inputParams[0]);
                List<string> returnLines = new List<string>();
                string decompressedFileName = GetDecompressedLogPath(tenantId, (DateTime)inputParams[1]);

                if (File.Exists(decompressedFileName))
                {
                    if (value == null)
                    {
                        //If no filter is specified the local path is returned
                        returnLines.Add(decompressedFileName);
                        return returnLines;
                    }

                    var keywords = (List<string>)value;
                    var logLines = File.ReadAllLines(decompressedFileName);
                    if (logLines != null && logLines.Length > 0)
                    {
                        foreach (string line in logLines)
                        {
                            foreach (var keyword in keywords)
                            {
                                if (line.Contains(keyword))
                                {
                                    returnLines.Add(line);
                                }
                            }
                        }
                    }
                }

                return returnLines;
            }

            return null;
        }

        public void Delete(object contextData, object value)
        {
            string tenantId = Convert.ToString(contextData);
            DateTime date = (DateTime)value;
            string prevCompressedFile = GetCompressedLogPath(tenantId, date);
            string prevDecompreesedFileName = GetDecompressedLogPath(tenantId, date);

            if (File.Exists(prevCompressedFile))
            {
                File.Delete(prevCompressedFile);
            }

            if (File.Exists(prevDecompreesedFileName))
            {
                File.Delete(prevDecompreesedFileName);
            }
        }
    }
}
